package com.lk.client.proxy;

import com.lk.client.rpc.RpcClient;
import com.lk.entity.RequestMessage;
import io.netty.channel.Channel;
import io.netty.util.concurrent.DefaultPromise;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.concurrent.atomic.AtomicInteger;

import static com.lk.client.rpc.handler.RpcResponseMessageHandler.promises;

/**
 * @author kun.li
 */
public class JdkProxy implements InvocationHandler {


    private Class zClass;
    private String version;
    private String beanName;

    public JdkProxy(Class zClass, String version, String beanName) {
        this.zClass = zClass;
        this.version = version;
        this.beanName = beanName;
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        System.out.println("调用前");
        int nextId = nextId();
        RequestMessage msg = new RequestMessage(
                zClass.getName(),
                method.getName(),
                method.getReturnType(),
                method.getParameterTypes(),
                args
        );
        msg.setBeanName(beanName);
        msg.setVersion(version);
        msg.setSequenceId(nextId);
        Channel channel = RpcClient.getInstance().start();
//        Channel channel = getChannel();
        channel.writeAndFlush(msg);
        DefaultPromise<Object> promise = new DefaultPromise<>(channel.eventLoop());
        promises.put(nextId, promise);
        promise.await();
        if (promise.isSuccess()) {
            return promise.getNow();
        }
        return promise.cause().getMessage();
    }

    public static <T> T getProxy(Class<T> serviceClass) {
        ClassLoader classLoader = serviceClass.getClassLoader();
        Class<?>[] interfaces = new Class[]{serviceClass};
        Object instance = Proxy.newProxyInstance(classLoader, interfaces, new JdkProxy(serviceClass, "1.0", ""));
        return (T) instance;
    }

    public static <T> T getProxy(Class<T> serviceClass, String version) {
        ClassLoader classLoader = serviceClass.getClassLoader();
        Class<?>[] interfaces = new Class[]{serviceClass};
        Object instance = Proxy.newProxyInstance(classLoader, interfaces, new JdkProxy(serviceClass, version,""));
        return (T) instance;
    }
    public static <T> T getProxy(Class<T> serviceClass,String beanName,String version) {
        ClassLoader classLoader = serviceClass.getClassLoader();
        Class<?>[] interfaces = new Class[]{serviceClass};
        Object instance = Proxy.newProxyInstance(classLoader, interfaces, new JdkProxy(serviceClass, version,beanName));
        return (T) instance;
    }
    private static final AtomicInteger atomicInteger = new AtomicInteger(0);

    public static int nextId() {
        return atomicInteger.incrementAndGet();
    }
}
